﻿#include "DataCenter.h"
#include <QDir>
#include <QHash>
#include <QJsonObject>
#include <QMutexLocker>
#include <QStandardPaths>
#include "../Debug.h"
#include "../Network/NetClient.h"
#include "../Toast.h"
namespace model
{
DataCenter* DataCenter::instance = nullptr;

DataCenter::DataCenter()
{
    login_session_id = "";
    cur_session_id   = "";
    member_list      = new QHash<QString, QList<UserInfo>>();
    message_list     = new QHash<QString, QList<Message>>();
    unread_count     = new QHash<QString, int>();
    net_client       = new NetClient(this);
    /* 其它属性不初始化的原因是用 nullptr 表示无效值 */
    init_data_file();
}

/// @brief 返回 DataCenter 的单例实例
/// @return
DataCenter* DataCenter::get_instance()
{
    if (instance == nullptr) {
        instance = new DataCenter();
    }
    return instance;
}
/// @brief 初始化数据文件
void DataCenter::init_data_file()
{
    /* 使用 appData目录 */
    QString appDataPath  = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    appDataPath         += "/ChatApp";
    /* 如果目录不存在则创建 */
    QDir appDataDir(appDataPath);
    if (!appDataDir.exists()) {
        bool res = appDataDir.mkpath(appDataPath);
        if (res == false) {
            LOG() << "Failed to create app data directory: " << appDataPath;
            return;
        }
    }
    appDataPath    += "/data.json";  // 数据文件名
    data_file_path  = appDataPath;
    /* 读取配置文件中的内容 */
    read_data_file();
    ///* 指定写入的内容 */
    // QString content = "{\n\n}";  // 初始化为空的JSON对象
    ///* 写入, 不存在文件将创建 */
    // write_file(appDataPath, content.toUtf8());
}

/// @brief 写入数据文件
void DataCenter::write_data_file()
{
    QJsonObject json_data;
    /* 写入登录会话id未读消息次数 */
    json_data["login session id"] = login_session_id;
    QJsonObject unread_obj;
    assert(unread_count);
    for (const auto& [key, value] : unread_count->asKeyValueRange()) {
        unread_obj[key] = value;
    }
    json_data["unread count"] = unread_obj;
    /* 构建 json 结构体 */
    QJsonDocument jsonDoc(json_data);
    QString       content = jsonDoc.toJson();
    /* 写入文件 */
    write_file(data_file_path, content.toUtf8());
}

/// @brief 从数据文件中读取数据
void DataCenter::read_data_file()
{
    /* 解析 json 结构体 */
    QJsonDocument json_doc = QJsonDocument::fromJson(read_file(data_file_path));
    if (json_doc.isNull()) {
        LOG() << "Failed to parse JSON from data file: " << data_file_path;
        return;
    }
    /* 将解析出来的内容放到类中的属性当中 */
    QJsonObject jsonData = json_doc.object();
    login_session_id     = jsonData["login session id"].toString();
    this->unread_count->clear();
    QJsonObject unread_obj = jsonData["unread count"].toObject();
    for (auto it = unread_obj.constBegin(); it != unread_obj.constEnd(); ++it) {
        // it.key() 是 QString，it.value() 是 QJsonValue
        unread_count->insert(it.key(), it.value().toInt());
    }
}

/// @brief 返回登录会话ID
QString DataCenter::get_login_session_id() const
{
    return login_session_id;
}

/// @brief 获取当前用户信息
UserInfo* DataCenter::get_cur_user_info() const
{
    return cur_user_info;
}

/// @brief 获取好友列表
QList<UserInfo>* DataCenter::get_friend_list() const
{
    return friend_list;
}

/// @brief 获取会话列表
QList<ChatSession>* DataCenter::get_chat_session_list() const
{
    return chat_session_list;
}

/// @brief 获得好友申请列表
QList<UserInfo>* DataCenter::get_friend_apply_list() const
{
    return apply_list;
}

/// @brief 获得消息列表
QList<Message>* DataCenter::get_message_list(const QString& chat_session_id) const
{
    if (message_list->count(chat_session_id) == 0) {
        return nullptr;
    } else {
        return &((*message_list)[chat_session_id]);
    }
}

/// @brief 返回这个 chat_session_id对应的会话
ChatSession* DataCenter::get_chat_session(const QString& chat_session_id) const
{
    if (chat_session_list == nullptr) {
        LOG() << "chat_session_list is nullptr";
        return nullptr;
    }
    for (auto& chat_session : *chat_session_list) {
        if (chat_session_id == chat_session.chat_session_id) {
            return &chat_session;
        }
    }
    LOG() << "chat_session_list don't have a match id, chat_session_id: " << chat_session_id;
    return nullptr;
}

/// @brief 通过用户ID 获得这个用户对应的会话, 当点击好友头像时会调用这个函数来查找
ChatSession* DataCenter::get_chat_session_by_user_id(const QString& user_id) const
{
    if (user_id == nullptr) {
        LOG() << "user_is is nullptr";
        return nullptr;
    }
    if (chat_session_list == nullptr) {
        LOG() << "chat_session_list is nullptr";
        return nullptr;
    }
    for (auto& chat_session : *chat_session_list) {
        if (user_id == chat_session.user_id) {
            return &chat_session;
        }
    }
    LOG() << "chat_session_list don't have a match id, user_id: " << user_id;
    return nullptr;
}

/// @brief 通过 user_id 获得这个用户对应的用户信息
UserInfo* DataCenter::get_user_info_by_user_id(const QString& user_id) const
{
    if (user_id.isEmpty() || user_id == nullptr || friend_list == nullptr) {
        LOG() << "Invalid argument!";
        return nullptr;
    }
    for (auto& user_info : *friend_list) {
        if (user_id == user_info.user_id) {
            return &user_info;
        }
    }
    LOG() << "Not found: " << user_id;
    return nullptr;
}

/// @brief 获取当前选中的会话ID
const QString DataCenter::get_cur_session_id() const
{
    return cur_session_id;
}

/// @brief 获取验证码ID
const QString& DataCenter::get_phone_verify_code_id() const
{
    return phone_verify_code_id;
}

/// @brief 设置当前选中的会话ID
void DataCenter::set_cur_session_id(const QString& chat_session_id)
{
    this->cur_session_id = chat_session_id;
}

/// @brief 通过 GetUserInfoRsp 这个PB结构体指针 设置当前用户信息
void DataCenter::set_cur_user_info(std::shared_ptr<chat::GetUserInfoRsp> user_info_resp)
{
    if (user_info_resp == nullptr) {
        LOG() << "set_cur_user_info: user_info_resp is null";
        return;
    }
    if (cur_user_info == nullptr) {
        cur_user_info = new UserInfo();
    }
    cur_user_info->load(user_info_resp->userInfo());
}

/// @brief 通过 GetFriendListRsp 这个PB结构体指针 设置当前用户信息
void DataCenter::set_friend_list(std::shared_ptr<chat::GetFriendListRsp> friend_list_resp)
{
    if (friend_list_resp == nullptr) {
        LOG() << "friend_list_resp is null";
        return;
    }
    if (friend_list == nullptr) {
        friend_list = new QList<UserInfo>();
    }
    friend_list->clear();
    for (const auto& user_info : friend_list_resp->friendList()) {
        UserInfo user;
        user.load(user_info);
        friend_list->append(user);
    }
}

/// @brief 通过 GetChatSessionListReq 这个PB结构体指针 设置当前用户信息
void DataCenter::set_chat_session_list(std::shared_ptr<chat::GetChatSessionListRsp> chat_session_list_resp)
{
    if (chat_session_list_resp == nullptr) {
        LOG() << "chat_session_list_resp is null";
        return;
    }
    if (chat_session_list == nullptr) {
        chat_session_list = new QList<ChatSession>();
    }
    chat_session_list->clear();
    for (auto chat_session_info : chat_session_list_resp->chatSessionInfoList()) {
        ChatSession chat_session;
        chat_session.load(chat_session_info);
        chat_session_list->append(chat_session);
    }
}

/// @brief 通过 GetPendingFriendEventListRsp 这个PB结构体指针 设置当前收到的待处理的好友申请列表
void DataCenter::set_friend_apply_list(std::shared_ptr<chat::GetPendingFriendEventListRsp> friend_apply_list_resp)
{
    if (friend_apply_list_resp == nullptr) {
        LOG() << "friend_apply_list_resp is null";
        return;
    }
    if (apply_list == nullptr) {
        apply_list = new QList<UserInfo>();
    }
    apply_list->clear();
    for (const auto& event : friend_apply_list_resp->event()) {
        UserInfo user;
        user.load(event.sender());
        apply_list->append(user);
    }
}

/// @brief 通过 GetRecentMsgRsp 这个PB结构体指针 设置当前收到的消息列表
void DataCenter::set_recent_messages(const QString& chat_session_id, std::shared_ptr<chat::GetRecentMsgRsp> recent_messages)
{
    if (message_list == nullptr) {
        LOG() << "message_list is NULL";
        return;
    }
    QList<Message> messages = (*message_list)[chat_session_id];  // 获取到这个chat_session_id对应的列表, 向其中添加消息
    messages.clear();
    for (const auto& message_info : recent_messages->msgList()) {
        Message message;
        message.load(message_info);
        messages.append(message);
    }
    message_list->insert(chat_session_id, messages);
}

/// @brief 设置个人信息的昵称
void DataCenter::set_cur_user_info_nick_name(const QString& nick_name)
{
    if (cur_user_info == nullptr) {
        LOG() << "cur_user_info is nullptr!!";
        return;
    }
    cur_user_info->nick_name = nick_name;
}

/// @brief 设置个人信息的个性签名
void DataCenter::set_cur_user_info_desc(const QString& desc)
{
    if (cur_user_info == nullptr) {
        LOG() << "cur_user_info is nullptr!!";
        return;
    }
    cur_user_info->description = desc;
}

/// @brief 设置个人信息的手机号
void DataCenter::set_cur_user_info_phone_num(const QString& phone_num)
{
    if (cur_user_info == nullptr) {
        LOG() << "cur_user_info is nullptr!!";
        return;
    }
    cur_user_info->phone_num = phone_num;
}

/// @brief 设置验证码的ID
void DataCenter::set_phone_verify_code_id(std::shared_ptr<chat::PhoneVerifyCodeRsp> verify_code_resp)
{
    if (verify_code_resp == nullptr) {
        LOG() << "verify_code_id is nullptr!!";
        return;
    }
    this->phone_verify_code_id = verify_code_resp->verifyCodeId();
}

/// @brief 设置当前用户的头像
void DataCenter::set_cur_user_info_avatar(const QByteArray& image)
{
    if (cur_user_info == nullptr) {
        LOG() << "cur_user_info is nullptr!!";
        return;
    }
    cur_user_info->avatar = make_icon(image);
}

/// @brief 将这个会话列表放入到 member_list 中
void DataCenter::add_group_member_list(const QString& chat_session_id, std::shared_ptr<chat::GetChatSessionMemberRsp> spec_member_list_rsp)
{
    if (spec_member_list_rsp == nullptr || member_list == nullptr) {
        LOG() << "Invalid param!";
        return;
    }
    QList<UserInfo> user_list;
    for (const auto& user_info : spec_member_list_rsp->memberInfoList()) {
        UserInfo m_user_info;
        m_user_info.load(user_info);
        user_list.push_back(m_user_info);
    }
    member_list->insert(chat_session_id, user_list);
}

/// @brief 获取指定会话ID的成员列表
QList<UserInfo> DataCenter::get_group_member_list(const QString& chat_session_id)
{
    if (chat_session_id == nullptr || chat_session_id.isEmpty() || member_list == nullptr) {
        LOG() << "Invalid param";
        return QList<UserInfo>();
    }
    return member_list->value(chat_session_id);
}

/// @brief 设置搜索到的用户列表
void DataCenter::set_search_user_result(std::shared_ptr<chat::FriendSearchRsp> search_rsp)
{
    if (search_rsp == nullptr) {
        LOG() << "Invalid param";
        return;
    }
    if (search_user_result == nullptr) {
        search_user_result = new QList<UserInfo>();
    }
    search_user_result->clear();
    for (const auto& user_info : search_rsp->userInfo()) {
        UserInfo m_user_info;
        m_user_info.load(user_info);
        search_user_result->append(m_user_info);
    }
}

/// @brief 获得搜索结果
QList<UserInfo>* DataCenter::get_search_user_result()
{
    return search_user_result;
}

/// @brief 将PB的MessageInfo列表转化为 model 中的 search_message_result
void DataCenter::set_search_history_msg(const QList<chat::MessageInfo>& pb_message)
{
    if (!search_message_result) {
        search_message_result = new QList<Message>();
    }
    search_message_result->clear();
    for (const auto& message : pb_message) {
        Message m_message;
        m_message.load(message);
        search_message_result->append(m_message);
    }
}

/// @brief 获得搜索消息结果
/// @return 
QList<Message>* DataCenter::get_search_message_result()
{
    return search_message_result;
}

/// @brief 登录后获得登录会话ID
void DataCenter::set_login_session_id(const QString& login_session_id)
{
    this->login_session_id = login_session_id;
    write_data_file();
}

/// @brief 删除某个指定的好友, 指定好友ID
void DataCenter::del_sepc_friend(const QString& user_id)
{
    if (friend_list == nullptr || chat_session_list == nullptr) {
        LOG() << "Invalid state!!";
        return;
    }
    /* 从好友列表中删除 */
    friend_list->removeIf([=](const UserInfo& user_info) {
        return user_info.user_id == user_id;  // 为true就删除
    });
    /* 从聊天会话中删除 */
    chat_session_list->removeIf([=](const ChatSession& chat_session) {
        if (chat_session.user_id == user_id) {
            /* 如果要删除的会话是当前选中的会话, 发送信号, 让MainWidget处理 */
            if (cur_session_id == chat_session.chat_session_id) {
                cur_session_id.clear();  // 当前会话置空
                emit del_cur_session();
            }
            return true;
        }
    });
}

/// @brief 把这个 user_id 对应的会话置顶, 也就是把这个会话放到 chat_session_list 的最前面
int DataCenter::top_this_session(/*const QString& user_id*/ ChatSession* this_session)
{
    if (!this_session || !chat_session_list) {
        LOG() << "Invalid arguments";
        return -1;
    }
    // 使用QMutexLocker防止多线程访问冲突
    QMutexLocker locker(&session_list_mutex);
    /* 查找会话位置 */
    int index = -1;
    for (int i = 0; i < chat_session_list->size(); ++i) {
        if (chat_session_list->at(i).user_id == this_session->user_id) {
            // LOG() << "Found session at index " << i;
            index = i;
            break;
        }
    }

    if (index == -1) {
        LOG() << "Session not found for user:" << this_session->user_id;
        return -1;
    }

    // LOG() << "ready to move, index: " << index;
    /* 移动到最前 */
    chat_session_list->move(index, 0);
    // LOG() << "end to move, index: " << index;

    // 确保有返回值
    return 0;
}

/// @brief 向指定的聊天会话列表中添加消息
void DataCenter::push_back_message_list(const QString& chat_session_id, const Message& message)
{
    if (get_chat_session(chat_session_id) == nullptr) {
        LOG() << "not this session: " << chat_session_id;
        return;
    }
    (*message_list)[chat_session_id].push_back(message);
}

/// @brief 增加这个会话id的未读消息数
void DataCenter::add_unread_cnt(const QString& chat_session_id)
{
    (*unread_count)[chat_session_id] += 1;
    write_data_file();
}

/// @brief 获取这个会话id的未读消息数
int DataCenter::get_unread_cnt(const QString& chat_session_id)
{
    return (*unread_count)[chat_session_id];
}

/// @brief 清楚这个会话id的未读消息数
void DataCenter::clear_unread_cnt(const QString& chat_session_id)
{
    (*unread_count)[chat_session_id] = 0;
    write_data_file();
}

/// @brief 当前用户是否是好友
bool DataCenter::is_friend(const QString& user_id)
{
    if (friend_list == nullptr) {
        LOG() << "friend list is nullptr!";
        return false;
    }
    for (const auto& user : *friend_list) {
        if (user.user_id == user_id) {
            return true;
        }
    }
    return false;
}

/// @brief 把这个用户信息头插到好友申请列表中
void DataCenter::push_front_apply_list(const UserInfo& user_info)
{
    if (apply_list == nullptr) {
        LOG() << "apply list is nullptr!";
        return;
    }
    apply_list->push_front(user_info);
}

/// @brief 从申请列表中删除一个用户
/// @param user_id
/// @return 删除的元素
UserInfo DataCenter::remove_from_apply_list(const QString& user_id)
{
    for (auto it = apply_list->begin(); it != apply_list->end(); ++it) {
        if (it->user_id == user_id) {
            auto user_info = *it;
            apply_list->erase(it);
            return user_info;
        }
    }
    LOG() << "not found this user: " << user_id;
    return UserInfo();
}

/// @brief 将用户信息头插到好友列表中
void DataCenter::push_front_friend_list(const UserInfo& user_info)
{
    if (friend_list == nullptr) {
        LOG() << "friend list is nullptr!";
        return;
    }
    friend_list->push_front(user_info);
}

/// @brief 进行 http 测试操作, 服务端会返回一个 pong 消息
void DataCenter::ping()
{
    /* 发送 ping 请求 */
    net_client->ping();
}

/// @brief 初始化网络套接字, 会向服务器发送身份认证信息
void DataCenter::init_socket()
{
    net_client->init_web_socket();
}

/// @brief 异步获取当前用户的信息。
void DataCenter::get_myself_info_async()
{
    net_client->get_myself_info(login_session_id);
}

/// @brief 异步获取好友列表
void DataCenter::get_friend_list_async()
{
    net_client->get_friend_list(login_session_id);
}

/// @brief 异步获取会话列表
void DataCenter::get_chat_session_list_async()
{
    net_client->get_chat_session_list(login_session_id);
}

/// @brief 异步获取好友申请列表
void DataCenter::get_friend_apply_list_async()
{
    net_client->get_friend_apply_list(login_session_id);
}

/// @brief 异步获取当前id的消息列表
/// @update_ui: 是否更新UI
void DataCenter::get_recent_messages_async(const QString& chat_session_id, int cnt, bool update_ui)
{
    net_client->get_recent_messages(login_session_id, chat_session_id, cnt, update_ui);  // 获取50条消息
}

/// @brief 异步发送文本消息
void DataCenter::send_text_message_async(const QString& chat_session_id, const QString& content)
{
    net_client->send_message(login_session_id, chat_session_id, MessageType::TEXT_TYPE, content.toUtf8(), "");
}

/// @brief 异步发送图片消息
void DataCenter::send_image_message_async(const QString& chat_session_id, const QByteArray& image)
{
    net_client->send_message(login_session_id, chat_session_id, MessageType::IMAGE_TYPE, image, "");
}

/// @brief 异步发送文件消息
void DataCenter::send_file_message_async(const QString& chat_session_id, const QByteArray& file_data, const QString& file_name)
{
    net_client->send_message(login_session_id, chat_session_id, MessageType::FILE_TYPE, file_data, file_name);
}

/// @brief 异步发送语音消息
void DataCenter::send_speech_message_async(const QString& chat_session_id, const QByteArray& audio_data)
{
    net_client->send_message(login_session_id, chat_session_id, MessageType::SPEECH_TYPE, audio_data, "");
}

/// @brief 从net client收到消息
void DataCenter::receive_message(const QString& chat_session_id)
{
    /* 获得消息列表的最后一条消息 */
    if (message_list == nullptr) {
        LOG() << "message_list is nullptr";
        return;
    }
    Message last_message = (*message_list)[chat_session_id].last();
    if (chat_session_id == cur_session_id) {
        /* 选中的会话是当前的会话, 去MessageShowArea中更新界面上的数据
           这里把连接信号槽的操作放到了MessageEditArea中. 让它来去MessageShowArea更新消息内容 */
        emit receive_message_done(last_message);
    } else {
        /* 更新未读消息 */
        add_unread_cnt(chat_session_id);
    }
    /* 都需要更新最后一条消息的展示. 处理这个的槽函数再SessionItem中定义 */
    emit update_last_message(chat_session_id);
    Toast::showMessage("收到消息!!");
}

/// @brief 异步设置用户昵称
void DataCenter::set_user_nick_name_async(const QString& nick_name)
{
    net_client->set_user_nick_name(login_session_id, nick_name);
}

/// @brief 异步设置用户个性签名
void DataCenter::set_user_description_async(const QString& desc)
{
    net_client->set_user_description(login_session_id, desc);
}

/// @brief 异步设置用户手机号
void DataCenter::set_user_phone_num_async(const QString& phone_num, const QString& phone_verify_code_id, const QString& phone_verify_code)
{
    net_client->set_user_phone_num(login_session_id, phone_num, phone_verify_code_id, phone_verify_code);
}

/// @brief 异步获取手机验证码
void DataCenter::get_phone_verify_code_async(const QString& phone_num)
{
    net_client->get_phone_verify_code(phone_num);  // 这里不需要登录会话id, 因为登录时也需要验证码
}

/// @brief 异步设置用户头像
void DataCenter::set_user_avatar_async(const QByteArray& image)
{
    net_client->set_user_avatar(login_session_id, image);
}

/// @brief 异步删除好友
void DataCenter::del_friend_async(const QString& user_id)
{
    net_client->del_friend(login_session_id, user_id);
}

/// @brief 异步添加好友申请
void DataCenter::add_friend_async(const QString& user_id)
{
    net_client->add_friend(login_session_id, user_id);
}

/// @brief 异步接受好友申请
void DataCenter::accept_friend_apply_async(const QString& user_id)
{
    net_client->accept_friend_apply(login_session_id, user_id);
}

/// @brief 异步拒绝好友申请
void DataCenter::reject_friend_apply_async(const QString& user_id)
{
    net_client->reject_friend_apply(login_session_id, user_id);
}

/// @brief 异步创建群组
void DataCenter::create_group_async(const QList<QString>& user_ids)
{
    net_client->create_group(login_session_id, user_ids);
}

/// @brief 异步获得指定session_id的群组成员列表
void DataCenter::get_group_member_list_async(const QString& chat_session_id)
{
    net_client->get_group_member_list(login_session_id, chat_session_id);
}

/// @brief 异步获得指定key的用户信息
void DataCenter::search_user_async(const QString& search_key)
{
    net_client->search_user(login_session_id, search_key);
}

/// @brief 异步获取指定会话id, 指定key的群消息, 根据关键字获取
void DataCenter::search_history_message_async(const QString& chat_session_id, const QString& search_key)
{
    net_client->search_history_message(login_session_id, chat_session_id, search_key);
}

/// @brief 异步获取指定会话id的群消息, 根据时间获取
void DataCenter::search_history_message_by_time_async(const QString& chat_session_id, qint64 start_time, qint64 end_time)
{
    net_client->search_history_message_by_time(login_session_id, chat_session_id, start_time, end_time);
}

/// @brief 异步使用用户名登录
void DataCenter::user_login_async(const QString& user_name, const QString& pwd)
{
    net_client->user_login(user_name, pwd);
}

/// @brief 异步使用用户名注册
void DataCenter::user_register_async(const QString& user_name, const QString& pwd)
{
    net_client->user_register(user_name, pwd);
}

/// @brief 异步使用手机号登录
void DataCenter::phone_login_async(const QString& phone_num, const QString& verify_code)
{
    net_client->phone_login(phone_num, verify_code);
}

/// @brief 异步使用手机号注册
void DataCenter::phone_register_async(const QString& phone_num, const QString& verify_code)
{
    net_client->phone_register(phone_num, verify_code);
}

/// @brief 异步获取文件内容
void DataCenter::get_single_file_async(const QString& file_id)
{
    net_client->get_single_file(login_session_id, file_id);
}

/// @brief 异步进行语音识别
void DataCenter::speech_recognition_async(const QByteArray& data)
{
    net_client->speech_recognition(login_session_id, data);
}
}  // end namespace model